package com.atguigu.tingshu.user.service.impl;

import com.alibaba.fastjson.JSON;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.rabbit.constant.MqConst;
import com.atguigu.tingshu.common.rabbit.service.RabbitService;
import com.atguigu.tingshu.common.util.MongoUtil;
import com.atguigu.tingshu.model.user.UserListenProcess;
import com.atguigu.tingshu.user.service.UserListenProcessService;
import com.atguigu.tingshu.vo.album.TrackStatMqVo;
import com.atguigu.tingshu.vo.user.UserListenProcessVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;


import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Service
@SuppressWarnings({"all"})
public class UserListenProcessServiceImpl implements UserListenProcessService {

    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private RabbitService rabbitService;

    /**
     * 根据用户ID获取最近的播放记录
     * 该方法通过查询MongoDB中特定用户集合的最新记录来获取用户最近播放的音乐信息
     *
     * @param userId 用户ID
     * @return 包含最近播放音乐的ID和专辑ID的映射如果找不到播放记录，则返回空映射
     */
    @Override
    public Map<String, Object> getLatelyTrack(Long userId) {
        // 构造集合名称，特定位于是用户的播放记录集合
        String collectionName = MongoUtil.getCollectionName(MongoUtil.MongoCollectionEnum.USER_LISTEN_PROCESS, userId);

        // 创建查询对象，并设置按更新时间降序排序，只获取一条记录
        Query query = new Query();
        query.with(Sort.by(Sort.Direction.DESC,"updateTime")).limit(1);

        // 执行查询，获取用户播放记录列表
        List<UserListenProcess> userListenProcessList = this.mongoTemplate.find(query, UserListenProcess.class, collectionName);

        // 如果播放记录列表不为空，则构建并返回包含播放信息的映射
        if (userListenProcessList.size()>0){
            // 获取最新的播放记录
            UserListenProcess userListenProcess = userListenProcessList.get(0);
            // 创建映射对象以存放播放信息
            Map<String,Object> map=new HashMap<>();
            // 将音乐ID和专辑ID存入映射对象
            map.put("trackId",userListenProcess.getTrackId());
            map.put("albumId",userListenProcess.getAlbumId());
            // 返回包含播放信息的映射
            return map;
        }

        // 如果播放记录列表为空，则返回一个新的空映射
        return new HashMap<>();
    }

    /**
     * 根据曲目ID和用户ID获取用户的跳过时间
     * 此方法查询数据库以获取特定用户在听某曲目时的跳过时间
     * 如果找不到相应的用户听歌记录，则返回0
     *
     * @param trackId 曲目ID
     * @param userId 用户ID
     * @return 用户的跳过时间，如果找不到记录，则返回0
     */
    @Override
    public BigDecimal getTrackBreakSecond(Long trackId, Long userId) {
        // 创建一个新的查询对象
        Query query = new Query();
        // 添加查询条件，寻找特定的trackId和userId
        query.addCriteria(Criteria.where("trackId").is(trackId).and("userId").is(userId));
        // 根据用户ID获取特定的集合名称
        String collectionName = MongoUtil.getCollectionName(MongoUtil.MongoCollectionEnum.USER_LISTEN_PROCESS, userId);

        // 使用查询对象和集合名称在mongoTemplate中查找用户听歌过程记录
        UserListenProcess userListenProcess = mongoTemplate.findOne(query, UserListenProcess.class, collectionName);
        // 如果找到了相应的记录，则返回用户的跳过时间
        if (null != userListenProcess) {
            return userListenProcess.getBreakSecond();
        }
        // 如果没有找到相应的记录，则返回0
        return new BigDecimal("0");
    }

    /**
     * 更新用户的听歌进度
     * @param userListenProcessVo
     * @param userId
     */
    @Override
    public void updateListenProcess(UserListenProcessVo userListenProcessVo, Long userId) {
        // 根据用户ID和歌曲ID更新用户的听歌进程

        // 构造MongoDB的集合名称
        String collectionName = MongoUtil.getCollectionName(MongoUtil.MongoCollectionEnum.USER_LISTEN_PROCESS, userId);

        // 创建查询对象，查询条件为用户ID和歌曲ID
        Query query=new Query();
        query.addCriteria(Criteria.where("userId").is(userId).and("trackId").is(userListenProcessVo.getTrackId()));

        // 执行查询，获取用户听歌进程信息
        UserListenProcess userListenProcess = mongoTemplate.findOne(query, UserListenProcess.class, collectionName);

        // 如果查询结果为空，说明需要新建一条记录
        if (null==userListenProcess){
            userListenProcess=new UserListenProcess();
            userListenProcess.setId(UUID.randomUUID().toString().replace("-","")); // 生成记录ID
            userListenProcess.setUserId(userId);
            userListenProcess.setAlbumId(userListenProcessVo.getAlbumId());
            userListenProcess.setTrackId(userListenProcessVo.getTrackId());
            userListenProcess.setBreakSecond(userListenProcessVo.getBreakSecond());
            userListenProcess.setCreateTime(new Date()); // 设置创建时间
            userListenProcess.setUpdateTime(new Date()); // 设置更新时间
        }
        // 如果查询结果非空，说明需要更新现有记录
        else {
            userListenProcess.setBreakSecond(userListenProcessVo.getBreakSecond());
            userListenProcess.setUpdateTime(new Date()); // 更新时间
        }

        // 保存用户听歌进程信息到MongoDB
        this.mongoTemplate.save(userListenProcess,collectionName);

        // 构造Redis键值
        String key="userListenProcess"+userId+":"+userListenProcessVo.getTrackId();

        // 检查Redis中是否存在相同键值，如果存在则说明同一天内已播放过
        Boolean result=this.redisTemplate.opsForValue().setIfPresent(key,1,1, TimeUnit.DAYS);
        if (result){
            System.out.println("同一天播放");

            // 创建播放统计对象
            TrackStatMqVo trackStatMqVo = new TrackStatMqVo();
            trackStatMqVo.setTrackId(userListenProcessVo.getTrackId());
            trackStatMqVo.setStatType(SystemConstant.TRACK_STAT_PLAY);
            trackStatMqVo.setCount(1);
            trackStatMqVo.setBusinessNo(UUID.randomUUID().toString().replace("-",""));
            trackStatMqVo.setAlbumId(userListenProcessVo.getAlbumId());

            // 发送消息到RabbitMQ，更新播放统计
            rabbitService.sendMessage(MqConst.EXCHANGE_TRACK,MqConst.ROUTING_TRACK_STAT_UPDATE, JSON.toJSONString(trackStatMqVo));
        }

    }

}
